#include "Main.h"
#include "myMath.h"

void drawGrid()
{
	glColor3f(0.3,0.3,0.3);
	for(float i=-4.5;i<=4.5;i=i+0.5)
	{
		glLineWidth(0.1);
		glPushMatrix();
			glBegin(GL_LINES);
				glVertex3f(i,0.0,+5.0);
				glVertex3f(i,0.0,-5.0);
			glEnd();
			glBegin(GL_LINES);
				glVertex3f(+5.0,0.0,i);
				glVertex3f(-5.0,0.0,i);
			glEnd();
		glPopMatrix();
	}
}

void drawAxis(){
	//draw a green vertical line, 2.5 unit high
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_LINE_SMOOTH);
	glLineWidth(1.5);
	glColor3f(0.0,1.0,0.0);
	glPushMatrix();
		text(0,2.5,0,"y",1).print();
		glBegin(GL_LINES);
		glVertex2f(0.0,0.0);
		glVertex2f(0.0,2.5);
		glEnd();
	glPopMatrix();
	//Draw a red horizontal line, 2.5 units long
	glColor3f(1.0,0.0,0.0);
	glPushMatrix();
		text(2.5,0,0,"x",1).print();
		glBegin(GL_LINES);
		glVertex2f(0.0,0.0);
		glVertex2f(2.5,0.0);
		glEnd();
	glPopMatrix();
	//Draw a blue line coming out of the screen, 2.5 units long
	glColor3f(0.0,0.0,1.0);
	glPushMatrix();
		text(0,0,2.5,"z",1).print();
		glBegin(GL_LINES);
		glVertex3f(0.0,0.0,0.0);
		glVertex3f(0.0,0.0,2.5);
		glEnd();
	glPopMatrix();
	glEnable(GL_DEPTH_TEST);
}

void pointToAxis(TVector v)
{
glPushAttrib(GL_ENABLE_BIT); 
//glPushAttrib is done to return everything to normal after drawing

glLineStipple(4, 0xAAAA);  // [1]
glEnable(GL_LINE_STIPPLE);
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(v.X(),0.0,0.0);
glVertex3f(v.X(),v.Y(),v.Z());
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,v.Y(),0.0);
glVertex3f(v.X(),v.Y(),v.Z());
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,v.Z());
glVertex3f(v.X(),v.Y(),v.Z());
glEnd();

glPopAttrib();

}

void drawVector(TVector v)
{
	char coords[32];
	sprintf_s(coords,"%s %.2f %s %.2f %s %.2f","x=",v.X(),",y=",v.Y(),",z=",v.Z());
	text xyz(v.X()+0.3,v.Y(),v.Z(),coords,1); //text variable to print the coordinates 
	xyz.print();
	glLineWidth(1.5);
	glPushMatrix();
		glBegin(GL_LINES);
			glVertex3f(v.origin.X(),v.origin.Y(),v.origin.Z());
			glVertex3f(v.X()*0.95,v.Y()*0.95,v.Z()*0.95);
		glEnd();
		glBegin(GL_TRIANGLES);
			glVertex3f(v.X(),v.Y(),v.Z());
			glVertex3f(v.X()*0.90,v.Y()*0.96,v.Z()*0.91);
			glVertex3f(v.X()*0.96,v.Y()*0.90,v.Z()*0.91);
		glEnd();
	glPopMatrix();

//	pointToAxis(v);
}

void demoRotation(float demoAngle)
{
	Quaternion q1,q2,q2c,q3;
	q1=Quaternion(0,TVector(0,2,0));//Initial position 0,2,0
	float radAngle=deg2rad(demoAngle);
	q2=Quaternion(cos(radAngle/2),TVector(0*sin(radAngle/2),0*sin(radAngle/2),1*sin(radAngle/2)));//rotation quat
	q2.normalise();
	q2c=q2;
	q2c.conjugate();//conjugate 
	q3=q2*q1*q2c;//* is quat multiplication
	glPushMatrix();
	glTranslatef(-4,0,0);//move the x,y,z axis to the left
	drawAxis();
	glColor3f(0.6, 1.0, 1.0);
	drawVector(q3.v);
	glTranslatef(q3.v._x,q3.v._y,q3.v._z);//new location of the point
	glColor3f(0.0,0.0,1.0);
	glutWireSphere(0.3,10,10);
	glPopMatrix();


	glPushMatrix();
	glTranslatef(2,0,0);
	drawAxis();
	glRotatef(demoAngle,0,0,1);
		glColor3f(0.6, 1.0, 1.0);
		glBegin(GL_LINES);
			glVertex3f(0,0,0);
			glVertex3f(0,2,0);
		glEnd();
	glTranslatef(0,2,0);
	glColor3f(1.0,0.0,0.0);
	glutWireSphere(0.3,10,10);
	glPopMatrix();

	char details[62];
	//sprintf_s(details,"%s %.2f %s %.2f %s %.2f","x=",X(),",y=",v.Y(),",z=",v.Z());
	

	//Print quaternion rotation details
	glColor3f(0.0,0.0,1.0);
	text(-4.7,4.2,0,"Quaternion rotation",1).print(); //text variable to print the coordinates 
	sprintf_s(details,"Rotated q:%.2f %.2f %.2f %.2f",q3.w,q3.v._x,q3.v._y,q3.v._z);
	text(-4.75,4.0,0,details,1).print();
	sprintf_s(details,"Rotation q:%.2f %.2f %.2f %.2f",q2.w,q2.v._x,q2.v._y,q2.v._z);
	text(-4.8,3.8,0,details,1).print();
	sprintf_s(details,"sin(%.2f)=%.2f ; cos(%.2f)=%.2f",demoAngle/2,sin(deg2rad(demoAngle/2)),demoAngle/2,cos(deg2rad(demoAngle/2)));
	text(-4.85,3.6,0,details,1).print();

	//OpenGL rotation details
	glColor3f(1.0,0.0,0.0);
	text(3.0,4.2,0,"OpenGL rotation",1).print(); //text variable to print the coordinates 
	sprintf_s(details,"glRotatef(%.0f,0,0,1);",demoAngle);
	text(2.7,4.0,0,details,1).print();
	sprintf_s(details,"glTranslatef(0,2,0);");
	text(2.73,3.8,0,details,1).print();



	glColor3f(1.0,1.0,0.8);
	text(-2.0,4.2,0,"- Decrease angle <5 deg> Increase angle +",1).print(); //text variable to print the coordinates 
	text(-1.1,4.0,0," Start position (0,2,0)",1).print();
	sprintf_s(details,"Angle = %.f around Z axis",demoAngle);
	text(-1.2,3.8,0,details,1).print();
	
}

void demoDotProduct1()
{
	TVector v1,v2;
	v1=TVector(1,4,0);
	v1=v1.unit();
	v2=TVector(1.5,2,0);
	v2=v2.unit();

	char details[62];
	//sprintf_s(details,"%s %.2f %s %.2f %s %.2f","x=",X(),",y=",v.Y(),",z=",v.Z());

	drawAxis();
	glColor3f(0.6, 0.8, 0.4);
	drawVector(v1);
	sprintf_s(details,"v1: x=%.2f ,y=%.2f, z=%.2f",v1.X(),v1.Y(),v1.Z());
	text(-4.7,4.2,0,details,1).print();

	glColor3f(0.8, 0.6, 0.4);
	drawVector(v2);
	sprintf_s(details,"v2: x=%.2f ,y=%.2f, z=%.2f",v2.X(),v2.Y(),v2.Z());
	text(-4.75,4.0,0,details,1).print();

	glColor3f(1.0, 0.4, 0.4);
	sprintf_s(details,"v1*v2=x1*x2+y1*y2+z1*z2=%.5f",TVector::dotProduct(v1,v2));
	text(-4.81,3.8,0,details,1).print();
	
	glColor3f(0.2, 0.8, 1.0);
	sprintf_s(details,"angle(v1,v2): %f",TVector::getAngle(v1,v2));
	text(-4.86,3.6,0,details,1).print();

	glColor3f(1.0,1.0,0.8);
	text(-1.8,4.2,0,"Dot product of two unit vectors",1).print(); //text variable to print the coordinates 
}

void demoDotProduct2()
{
	TVector v1,v2;
	v1=TVector(1,4,0);
	v1=v1.unit();
	v2=TVector(1.5,2,0);

	char details[62];
	//sprintf_s(details,"%s %.2f %s %.2f %s %.2f","x=",X(),",y=",v.Y(),",z=",v.Z());

	drawAxis();
	glColor3f(0.6, 0.8, 0.4);
	drawVector(v1);
	sprintf_s(details,"v1: x=%.2f ,y=%.2f, z=%.2f",v1.X(),v1.Y(),v1.Z());
	text(-4.7,4.2,0,details,1).print();

	glColor3f(0.8, 0.6, 0.4);
	drawVector(v2);
	sprintf_s(details,"v2: x=%.2f ,y=%.2f, z=%.2f",v2.X(),v2.Y(),v2.Z());
	text(-4.75,4.0,0,details,1).print();

	glColor3f(1.0, 0.4, 0.4);
	sprintf_s(details,"v1*v2=x1*x2+y1*y2+z1*z2=%.5f",TVector::dotProduct(v1,v2));
	text(-4.81,3.8,0,details,1).print();

	glColor3f(0.2, 0.8, 1.0);
	sprintf_s(details,"angle(v1,v2): %f",TVector::getAngle(v1,v2));
	text(-4.86,3.6,0,details,1).print();

	glColor3f(1.0,1.0,0.8);
	text(-1.8,4.2,0,"Dot product of unit & general vector",1).print(); //text variable to print the coordinates 
}

void demoCrossProduct()
{
	char details[65];
	TVector v1=TVector(1.5,0,3);
	TVector v2=TVector(3,1,2);
	v1=v1.unit();
	v2=v2.unit();

	TVector v3=v1*v2;

	drawAxis();
	glColor3f(0.6, 0.4, 0.0);
	drawVector(v1);
	sprintf_s(details,"v1: x=%.2f ,y=%.2f, z=%.2f",v1.X(),v1.Y(),v1.Z());
	text(-4.7,4.2,0,details,1).print();

	glColor3f(0.8, 0.4, 0.6);
	drawVector(v2);
	sprintf_s(details,"v2: x=%.2f ,y=%.2f, z=%.2f",v2.X(),v2.Y(),v2.Z());
	text(-4.75,4.0,0,details,1).print();

	glColor3f(1.0, 0.4, 0.2);
	drawVector(v3);
	sprintf_s(details,"v3: x=%.2f ,y=%.2f, z=%.2f",v3.X(),v3.Y(),v3.Z());
	text(-4.81,3.8,0,details,1).print();

	sprintf_s(details,"x3: y1*z2-z1*y2=%f",v3.X());
	text(-4.86,3.6,0,details,1).print();
	sprintf_s(details,"y3: z1*x2-x1*z2=%f",v3.Y());
	text(-4.92,3.4,0,details,1).print();
	sprintf_s(details,"z3: x1*y2-y1*x2=%f",v3.Z());
	text(-4.97,3.2,0,details,1).print();

	glColor3f(0.2, 0.8, 1.0);
	sprintf_s(details,"angle(v1,v2): %f",TVector::getAngle(v1,v2));
	text(-5.01,3.0,0,details,1).print();

	glColor3f(1.0,1.0,0.8);
	text(-1.8,4.2,0,"Cross product between 2 unit vectors",1).print(); //text variable to print the coordinates 
}

void demoIntro()
{
	char details[65];
	glColor3f(1.0,1.0,0.8);
	text(-1.0,3.2,0,"301 CR - Math Library",2).print(); //text variable to print stuff
	glColor3f(1.0, 1.0, 0.2);
	text(0.6,3.0,0,"by Florin N. Coada",1).print();
	text(0.9,2.8,0,"2887289",1).print();
	glColor3f(0.8, 1.0, 0.8);
	text(-0.3,2.6,0,"Controls :",2).print();
	text(-1.6,2.3,0,"# - Change camera(default recommended)",1).print();
	text(-1.4,2.0,0,"q,e - Zoom in/out (camera 2,3)",1).print();
	text(-1.4,1.7,0,"a,d - Left/right (camera 2,3)",1).print();
	text(-1.4,1.4,0,"w,s - Up/down (camera 2,3)",1).print();
	text(-2.4,1.1,0,"+,- - Increase/decrease rotation angle (Quaternions demo)",1).print();
	text(-1.6,0.8,0,"+,- - Increase/decrease lerp value",1).print();
	glColor3f(1.0, 0.0, 0.0);
	text(-0.9,0.5,0,"t - Start/Change demo",1).print();


}

void demoSubtract()
{
	char details[65];
	TVector v1(0.3,2,0);
	TVector v2(2.5,0.5,0);
	TVector v3=v1-v2;

	drawAxis();
	glColor3f(0.8, 0.6, 0.6);
	drawVector(v1);
	sprintf_s(details,"v1: x=%.2f ,y=%.2f, z=%.2f",v1.X(),v1.Y(),v1.Z());
	text(-4.7,4.2,0,details,1).print();

	glColor3f(1.0, 0.8, 0.2);
	drawVector(v2);
	sprintf_s(details,"v2: x=%.2f ,y=%.2f, z=%.2f",v2.X(),v2.Y(),v2.Z());
	text(-4.75,4.0,0,details,1).print();

	glColor3f(0.6, 0.6, 0.4);
	drawVector(v3);
	sprintf_s(details,"v3: x=%.2f ,y=%.2f, z=%.2f",v3.X(),v3.Y(),v3.Z());
	text(-4.81,3.8,0,details,1).print();

	v3.moveToOrigin(TPoint(v2._x,v2._y,v2._z));
	drawVector(v3);
	sprintf_s(details,"Move v3 to origin: x=%.2f ,y=%.2f, z=%.2f",v2.X(),v2.Y(),v2.Z());
	text(-4.86,3.6,0,details,1).print();
	sprintf_s(details,"v3: x=%.2f ,y=%.2f, z=%.2f",v3.X(),v3.Y(),v3.Z());
	text(-4.92,3.4,0,details,1).print();

	glColor3f(1.0,1.0,0.8);
	text(-1.8,4.2,0,"Subtraction operation v1-v2",1).print();

}

void demoLerp(float timeStep)
{
	char details[65];
	TPoint p1(1,1,1);
	TPoint p2(3,3,3);
	TPoint lerp;
	lerp=p1.lerp(p2,timeStep);


	glPushMatrix();
	glTranslatef(lerp._x,lerp._y,lerp._z);
	glColor3f(0.6,timeStep,0.4);
	glutWireSphere(0.3,10,10);
	glPopMatrix();
	drawAxis();

	glColor3f(0.8, 0.6, 0.6);
	sprintf_s(details,"p1: x=%.2f ,y=%.2f, z=%.2f",p1.X(),p1.Y(),p1.Z());
	text(-4.7,4.2,0,details,1).print();
	
	glColor3f(1.0, 0.8, 0.2);
	sprintf_s(details,"p2: x=%.2f ,y=%.2f, z=%.2f",p2.X(),p2.Y(),p2.Z());
	text(-4.75,4.0,0,details,1).print();

	glColor3f(0.6, timeStep, 0.4);
	sprintf_s(details,"Interpolation: x=%.2f ,y=%.2f, z=%.2f",lerp.X(),lerp.Y(),lerp.Z());
	text(-4.81,3.8,0,details,1).print();
	sprintf_s(details,"Interpolation value: %.2f",timeStep);
	text(-4.86,3.6,0,details,1).print();

	glColor3f(1.0,1.0,0.8);
	text(-1.6,4.2,0,"Interpolation of p1 and p2",1).print();
}
